import gevent
# from gevent import monkey
# monkey;monkey.patch_all() # 遇到耗时的操作（阻塞），monkey.patch_all()将耗时的操作自动转换gevent内部模块
# monkey.patch_all(thread = False,ssl=False,select=False) paramiko是不能使用猴子补丁的，这点作者在github上已经申明了。

import wmi,time,subprocess,socket
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor,wait,as_completed
from multiprocessing import Process, Queue
import multiprocessing
from confs import settings
from .ssh import client_ssh
# from Queue import Queue

tasks = []

class Win32Info (object):
    def __init__ (self,ip_list):
        self.ip_list = ip_list
        # self.wmi_obj = self.wmi_collection ()
        
    @staticmethod
    def scan (ip):
        try:
            s = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
            # print (s) # <gevent._socket3.socket
            # s.settimeout (1)
            s.connect ((ip,3389)) # 端口扫描，windows主机一般开启3389端口
            # print ('Ok')
            tasks.append (ip)
            # return tasks
        except Exception as e:
            # print ('e.args')
            pass
        s.close ()

    def wmi_collection (self,ip):
        try:
            # wmi_obj = wmi.WMI (computer = ip,user = r'.\admin',password = '2018.pw.')
            wmi_obj = wmi.WMI(computer=ip, user='administrator', password='123456')
            if wmi_obj:
                return wmi_obj
        except Exception as e:
            # print ('e.args')
            pass

    def c_freespace_disk (self,x):
            if x > 0.9:
                return 1
            else:
                return 0
        
    def collect (self,ip):
        # wmi_obj = wmi.WMI (computer = ip,user = r'.\admin',password = '123456')
        self.wmi_obj = self.wmi_collection (ip)
        self.wmi_obj.Win32_Process.Create (CommandLine = settings.SSH['cmd'])  # 每个windows电脑建立ssh连接

        c_disk = self.wmi_obj.Win32_LogicalDisk(Caption='C:')[0]
        c_free = int(c_disk.FreeSpace) / int(c_disk.Size)  # 显示C盘空闲比例'

        if self.wmi_obj.Win32_Process(name="ccSvcHst.exe"): # 是否运行杀毒程序
            ccSvcHst = 0
        else:
            ccSvcHst = 1

        data = {
            'os_name':self.wmi_obj.Win32_ComputerSystem()[0].Name, # 显示系统名称 'SIT-I44987-O'
            'os_system':self.wmi_obj.Win32_OperatingSystem()[0].Name [:24], # 显示操作系统 'Microsoft Windows 10
            'ip':ip,
            'c_disk':self.c_freespace_disk (c_free),
            'ccSvcHst':ccSvcHst,
            'username':client_ssh(ip)
            }

        # print (self.wmi_obj)
        # print (data)
        # 分别获取各种硬件信息
        data.update (self.get_cpu_info(ip)) # 更新键值
        data.update (self.get_ram_info(ip))
        data.update (self.get_disk_info(ip))
        data.update (self.get_nic_info(ip))
        # 最后返回一个数据字典
        # print (data)
        return data
        
    def asy (self):
        start_time = time.time ()
        g_l = [gevent.spawn (self.scan,ip) for ip in self.ip_list]
        gevent.joinall (g_l)
        # print (tasks)
        # print (len (tasks))
        print ('ping执行-->耗时{:.2f}'.format(time.time() - start_time))

        pool = multiprocessing.Pool(60) # 开启最大进程，max_workers = (os.cpu_count() or 1) * 5
        data = pool.map(self.collect,[ip for ip in tasks])
        pool.close()
        pool.join()
        print ('执行-->耗时{:.2f}'.format(time.time() - start_time))
        # print (data)

        return data
         
    def get_cpu_info (self,ip):
        """
        获取CPU的相关数据，这里只采集了三个数据，实际有更多，请自行选择需要的数据
        :return:
        """
        self.wmi_obj = self.wmi_collection (ip)
        data = {}
        cpu_lists = self.wmi_obj.Win32_Processor()
        cpu_core_count = 0
        for cpu in cpu_lists:
            cpu_core_count += cpu.NumberOfCores
            
        cpu_model = cpu_lists[0].Name # CPU型号（所有的CPU型号都是一样的）
        data ['cpu_cont'] = len (cpu_lists)  # CPU个数
        data ['cpu_model'] = cpu_model
        data ['cpu_core_count'] = cpu_core_count # CPU总的核数
        return data

        
    def get_ram_info (self,ip):
        """
        收集内存信息
        :return:
        """
        self.wmi_obj = self.wmi_collection (ip)
        data = []
        ram_collections = self.wmi_obj.Win32_PhysicalMemory()
        for ram in ram_collections:  # 主机中存在很多根内存，要循环所有的内存数据
            ram_size = int (int (ram.Capacity) / (1024**3)) # 转换内存单位为GB
            item_data = {
                'slot':ram.DeviceLocator.strip(),
                'capacity':ram_size,
                'model':ram.Caption,
                'manufacturer':ram.Manufacturer,
                'sn':ram.SerialNumber
                }
            data.append (item_data)  # 将每条内存的信息，添加到一个列表里
        return {'ram':data}   # 再对data列表封装一层，返回一个字典，方便上级方法的调用
        
    def get_disk_info (self,ip):
        """
        硬盘信息
        :return:
        """

        self.wmi_obj = self.wmi_collection (ip)
        data = []
        for disk in self.wmi_obj.Win32_DiskDrive ():  # 每块硬盘都要获取相应信息
            disk_data = {}
            interface_choices = ['SAS','SCSI','SATA','SSD']
            for interface in interface_choices:
                if interface in disk.InterfaceType:
                    disk_data ['interface_type'] = interface
                    break 
                else:
                    disk_data ['interface_type'] = 'SATA'
                
            disk_data ['slot'] = disk.index
            disk_data ['sn'] = disk.SerialNumber
            disk_data ['model'] = disk.Model
            disk_data ['manufacturer'] = disk.Manufacturer
            disk_data ['capacity'] =int (int (disk.Size) / (1024 **3))
            data.append (disk_data)
        
        return {'physical_disk_driver':data}
        
    def get_nic_info (self,ip):
        """
        网卡信息
        :return:
        """
        self.wmi_obj = self.wmi_collection (ip)
        data = []
        for nic in self.wmi_obj.Win32_NetworkAdapterConfiguration():
            if nic.MACAddress is not None:
                nic_data = {}
                nic_data['mac'] = nic.MACAddress
                nic_data ['model'] = nic.Caption
                nic_data['name'] = nic.Index
                if nic.IPAddress is not None:
                    nic_data ['ip_address'] = nic.IPAddress[0]
                    nic_data ['net_mask'] = nic.IPSubnet
                else:
                    nic_data ['ip_address'] = ''
                    nic_data ['net_mask'] = ''
                data.append (nic_data)
            
        return {'nic':data}

     
     
if __name__ == '__main__':
    # 测试代码
    start_time = time.time ()
    ip_list = []
    tasks = []
                
    for i in range (1,20):
            ip_list.append ('192.168.1.{}'.format (i))
            
    tasks = Win32Info(ip_list).asy()
    print (tasks)
    
        
    # for key in data:
        # print (key,':',data [key])
    print ('执行-->耗时{:.2f}'.format(time.time() - start_time))